<template>
  <a-modal
    :visible="visible"
    title="权限分配"
    :confirm-loading="confirmLoading"
    @cancel="handleCancel"
    @ok="handleOk"
    width="600px"
  >
    <div class="permission-tree-container">
      <a-spin :spinning="loading">
        <a-alert
          type="info"
          show-icon
          class="permission-alert"
          message="请选择该角色拥有的权限"
        />
        
        <!-- 权限树 -->
        <a-tree
          v-if="permissionTree.length"
          v-model:checkedKeys="checkedKeys"
          :tree-data="permissionTree"
          checkable
          :defaultExpandAll="true"
          :fieldNames="{
            children: 'children',
            title: 'title',
            key: 'key',
          }"
        />
        <a-empty v-else description="暂无权限数据" />
      </a-spin>
    </div>
  </a-modal>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'
import { message } from 'ant-design-vue'
import { usePermission } from '@/composables/usePermission'
import * as roleApi from '@/api/role'
import * as permissionApi from '@/api/permission'

const props = defineProps<{
  visible: boolean
  roleId?: number
}>()

const emit = defineEmits(['update:visible', 'success'])

// 权限相关
const { convertToTree } = usePermission()

// 加载状态
const loading = ref(false)
const confirmLoading = ref(false)

// 权限树数据
const permissionTree = ref<any[]>([])

// 选中的权限
const checkedKeys = ref<any[]>([])

// 权限映射表：用于快速查找权限的父权限和类型
// key: 权限ID (字符串，避免大整数精度丢失), value: { parentId, menuType }
const permissionMap = ref<Map<string, { parentId: string | null, menuType: number }>>(new Map())

// 原始权限树数据（保留完整信息）
const rawPermissionTree = ref<any[]>([])

// 监听visible变化
watch(
  () => props.visible,
  (val) => {
    if (val && props.roleId) {
      loadRolePermissions()
    }
  }
)

// 加载角色的权限数据
const loadRolePermissions = async () => {
  if (!props.roleId) return
  
  loading.value = true
  try {
    // 使用角色权限树接口，同时获取用户可见权限和角色已有权限
    const res = await permissionApi.getRolePermissionTree(props.roleId)
    
    // 处理权限树数据
    if (res && res.menus) {
      // 保存原始权限树数据
      rawPermissionTree.value = res.menus
      
      // 构建权限映射表
      buildPermissionMap(res.menus)
      
      // 转换树形数据为组件需要的格式
      permissionTree.value = formatBackendTreeData(res.menus)
      
      // 设置已选中的权限
      checkedKeys.value = res.checkedKeys || []
    } else {
      permissionTree.value = []
      rawPermissionTree.value = []
      permissionMap.value.clear()
      checkedKeys.value = []
    }
  } catch (error) {
    console.error('获取权限数据失败:', error)
    message.error('获取权限数据失败')
  } finally {
    loading.value = false
  }
}

// 构建权限映射表
const buildPermissionMap = (trees: any[]) => {
  permissionMap.value.clear()
  const traverse = (nodes: any[]) => {
    nodes.forEach(node => {
      // 后端返回的Tree结构：id, parentId, name, menuType等
      // 将ID转换为字符串，避免大整数精度丢失
      const permissionId = String(node.id)
      const parentId = node.parentId != null ? String(node.parentId) : null
      const menuType = node.menuType
      
      permissionMap.value.set(permissionId, {
        parentId: parentId,
        menuType: menuType
      })
      
      if (node.children && node.children.length > 0) {
        traverse(node.children)
      }
    })
  }
  traverse(trees)
}

// 处理后端返回的树形数据
const formatBackendTreeData = (trees: any[]): any[] => {
  return trees.map(item => {
    const node = {
      title: item.name || item.label, // 后端返回的树节点使用name或label表示标题
      key: item.id,      // 后端返回的树节点通常使用id表示键
      children: item.children ? formatBackendTreeData(item.children) : undefined
    }
    return node
  })
}

// 将权限列表转换为树组件需要的格式 (保留以便需要时使用)
const formatTreeData = (permissions: any[]): any[] => {
  return permissions.map(item => {
    const node = {
      title: item.permissionName,
      key: item.permissionId,
      children: item.children ? formatTreeData(item.children) : undefined
    }
    return node
  })
}

// 不再需要节点映射表

// 不再需要这些手动处理逻辑，使用Ant Design Vue的默认级联行为

// 取消
const handleCancel = () => {
  emit('update:visible', false)
  checkedKeys.value = []
}

// 确保包含父菜单权限
// 如果选中了某个菜单下的按钮权限，自动包含该菜单的权限
const ensureParentMenuPermissions = (selectedKeys: (string | number)[]): string[] => {
  // 将选中的权限ID统一转换为字符串类型，避免大整数精度丢失
  const stringKeys = selectedKeys.map(key => String(key))
  const result = new Set<string>(stringKeys)
  
  // 递归添加父菜单权限
  const addParentMenus = (permissionId: string) => {
    const permission = permissionMap.value.get(permissionId)
    if (!permission) return
    
    const { parentId, menuType } = permission
    
    // 如果当前权限的父权限存在
    if (parentId !== null && parentId !== undefined) {
      const parentPermission = permissionMap.value.get(parentId)
      
      // 如果父权限是菜单类型（type=2），且还没有被选中，则添加
      if (parentPermission && parentPermission.menuType === 2) {
        if (!result.has(parentId)) {
          result.add(parentId)
          // 递归处理父权限的父权限
          addParentMenus(parentId)
        }
      }
      // 如果父权限是目录类型（type=1），也需要添加（确保菜单可见）
      else if (parentPermission && parentPermission.menuType === 1) {
        if (!result.has(parentId)) {
          result.add(parentId)
          // 递归处理父权限的父权限
          addParentMenus(parentId)
        }
      }
    }
  }
  
  // 对每个选中的权限，检查并添加其父菜单权限
  stringKeys.forEach(permissionId => {
    addParentMenus(permissionId)
  })
  
  return Array.from(result)
}

// 确定
const handleOk = async () => {
  if (!props.roleId) return
  
  confirmLoading.value = true
  try {
    // 确保包含父菜单权限（返回字符串数组，避免大整数精度丢失）
    const finalPermissionIds = ensureParentMenuPermissions(checkedKeys.value)
    
    // 直接发送字符串数组给后端，后端会自动转换为 Long
    // 这样可以避免 JavaScript Number 类型的大整数精度丢失问题
    // 调用API保存角色权限
    try {
      await roleApi.assignPermissions(props.roleId, finalPermissionIds as (string | number)[])
      message.success('权限分配成功')
      
      // 关闭对话框并通知父组件
      emit('update:visible', false)
      emit('success')
    } catch (apiError) {
      console.error('保存权限分配失败，可能接口未实现:', apiError)
      message.warning('权限分配功能可能未实现，请联系后端开发人员')
      
      // 临时方案：仍然关闭对话框
      emit('update:visible', false)
    }
  } catch (error) {
    console.error('权限分配失败:', error)
    message.error('权限分配失败')
  } finally {
    confirmLoading.value = false
  }
}
</script>

<style scoped>
.permission-tree-container {
  max-height: 400px;
  overflow-y: auto;
}

.permission-alert {
  margin-bottom: 16px;
}
</style>
